# ----------------------------------------------------------------------------
#   (C) COPYRIGHT PiFi, 2014
#
#   FILE:
#       denon_avr_hw.py
#
#   DESCRIPTION:
#       This file contains the Denon AVR Hardware interface class
#
#   REFERENCES:
#       TODO
#
#   $Author: VNG $

# ----------------------------------------------------------------------------

# ----------------------------------------------------------------------------
# Imported Modules
# ----------------------------------------------------------------------------
import time
from denon_avr_serial import DenonAVRSerial

# ----------------------------------------------------------
# constants - volume limits

M_VOL_LIMIT         = 99
C_VOL_LOW_LIMIT     = 38
C_VOL_HIGH_LIMIT    = 62

# ----------------------------------------------------------
# constants - speakers

SPEAKERS = ['FL', 'FR', 'C', 'SW', 'SL', 'SR', \
            'SBL', 'SBR']

# ----------------------------------------------------------
# constants - sources

SOURCES = ['V.AUX', 'TV']

# ---------------------------------------------------------------------------
# ----------------------------------------------------------------------------


class DenonAVRResponse(object):

    # ----------------------------------------------------------
    # constants

    # ----------------------------------------------------------
    def __init__(self, data):
        super(SLFCraftworksResponse, self).__init__()

# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------

# ----------------------------------------------------------------------------
# CLASS:
#   DenonAVRHW
#
# DESCRIPTION:
#   DenonAVRHW Object, used for communication with the 
#   hardware via a serial port
#
# ----------------------------------------------------------------------------
class DenonAVRHW(Object):

    # ----------------------------------------------------------
    def __init__(self, simulation = False):
        super(SLFHwCraftworks, self).__init__()
        
        self._simulation = simulation
        self._serial = None

        # shadow registers

    # ----------------------------------------------------------
    def __del__(self):
    
        # make sure the serial port is disconnected
        self.shutdown()
            
    # ----------------------------------------------------------
    # ----------------------------------------------------------
    def initialise(self):
        print "initialise"

        try:            
            # connect to the serial device
            if self._simulation == False:
                self._serial = DenonAVRSerial()
                self._serial.connect()

            # send a keep alive
            self.keep_alive()

            # TODO: initialise the hardware state         
                        
        except:
            self._serial = None
            
    # ----------------------------------------------------------
    def shutdown(self):
        print "shutdown"

        # TODO: prepare the hardware for shutdown
        if self._serial != None:
            pass

        # disconnect the serial device
        if self._serial != None:
            self._serial.disconnect()

    # ----------------------------------------------------------
    def keep_alive(self):
        print "keep_alive"
        
        try:
            # try to reconnect if the link is down
            if (self._simulation == False) and (self._serial == None):
               self.initialise()

            if self._simulation:
                return DenonAVRResponse('OK')

            # get-system-status is used as a keep alive
            if self._serial != None:
                rsp = self._get_system_status()
            else:
                rsp = None
                
        except:
            # something went wrong with the connection
            print "connection failed: keep_alive"
            rsp = None
            if self._serial != None:
                self._serial.disconnect()
                self._serial = None
                            
        # return the response or None if there is an error
        return rsp

    # ----------------------------------------------------------
    # ----------------------------------------------------------
    def power(self, on = True):

        if on == True:
            command = 'PWON'
        elif on == False:
            command = 'PWSTANDBY'
        else:
            return False

    # ----------------------------------------------------------
    def master_volume(self, up = False, level = None):
        
        if level != None:

            if (level >= 0) and (level <= M_VOL_LIMIT):

                if level_str < 10:
                    level_str = '0' + str(level_str)

                else:
                    level_str = str(level)

                command = 'MV'+level_str

            else:
                return False

        else:
            if up == True:
                command = 'MVUP'

            elif up == False:
                command = 'MVDOWN'

            else:
                return False

    # ----------------------------------------------------------
    def channel_volume(self, speaker = 'FL', up = True, level = None):

        if speaker not in SPEAKERS:
            return False

        if level != None:
            if (level >= C_VOL_LOW_LIMIT) and 
            (level <= C_VOL_HIGH_LIMIT):
                level_str = str(level)

                command = 'CV' + speaker + level_str

            else:
                return False

        else:
            if up == True:
                command = 'CV' + speaker + 'UP'

            elif up == False:
                command = 'CV' + speaker + 'DOWN'

            else:
                return False

    # ----------------------------------------------------------
    def mute(self, mute = True):

        if mute == True:
            command = 'MUON'

        elif mute == False:
            command = 'MUOFF'

        else:
            return False

    # ----------------------------------------------------------
    def select_source(self, source = 'V.AUX'):

        if source not in SOURCES:
            return False

        command = 'SI' + source 

# ------------------------------------------------------------------------------------
# End Of File
# ------------------------------------------------------------------------------------
